package org.testframe;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 流程上下文
 *
 * @author 丁常磊
 * @date 2023/11/17 9:47
 */

public class FlowContext {

    private FlowBootStarter flowBootStarter;

    private WebDriver webDriver;

    private volatile Throwable error;

    private final Map<String, DataSource> dataSourceMap = new HashMap<>();

    private final Map<String, ElSelector> selectorMap = new HashMap<>();


    private final List<Closeable> closeableList = new ArrayList<>();

    private final Map<String, Object> store = new HashMap<>();

    public FlowBootStarter getFlowBootStarter() {
        return flowBootStarter;
    }

    public void setFlowBootStarter(FlowBootStarter flowBootStarter) {
        this.flowBootStarter = flowBootStarter;
    }

    /**
     * 获取一个key
     *
     * @param key
     * @return
     */
    public Object get(String key) {
        return store.get(key);
    }

    /**
     * 声明变量
     *
     * @param key
     * @param value
     * @return
     */
    public Object set(String key, Object value) {
        return store.put(key, value);
    }


    public void setError(Throwable error) {
        this.error = error;
    }

    public Throwable getError() {
        return error;
    }

    /**
     * 初始化 chrome浏览器
     */
    public void initChrome(String driverPath) {

        if (webDriver != null) {
            return;
        }

        System.setProperty("webdriver.chrome.driver", driverPath);

        ChromeOptions options = new ChromeOptions();
        //允许任何来源的远程连接，这样可以避免一些跨域问题。
        options.addArguments("--remote-allow-origins=*");
        //初始化 chrome 浏览器 driver 对象
        webDriver = new ChromeDriver(options);

        closeableList.add(() -> webDriver.close());

    }

    private void checkInit() {
        if (webDriver == null) {
            throw new IllegalStateException("浏览器尚未初始化!");
        }
    }

    public void open(String path) {
        checkInit();
        webDriver.get(path);
    }

    public void close() {
        for (Closeable closeable : closeableList) {
            try {
                closeable.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        dataSourceMap.clear();
    }

    public El findElBySelector(String css) {
        By by = By.cssSelector(css);
        return findEl(by);
    }

    public El findElByText(String text) {
        By by = By.xpath("//*[contains(text(),'" + text + "')]");
        return findEl(by);
    }

    private El lastEl;

    private El findEl(By by) {
        checkInit();

        try {
            WebElement element = webDriver.findElement(by);
            if (element == null) {
                return null;
            }
            lastEl = new El(element);
            return lastEl;
        } catch (Exception e) {
            return null;
        }
    }


    public El findElXpath(String xpath) {
        By by = By.xpath(xpath);
        return findEl(by);
    }

    public El getLastEl() {
        return lastEl;
    }

    public void putDataSource(String as, DataSource dataSource) {
        if (dataSource == null) {
            throw new RuntimeException("数据源无效!");
        }
        closeableList.add(dataSource);
        dataSourceMap.put(as, dataSource);
    }

    public DataSource getDataSource(String name) {
        return dataSourceMap.get(name);
    }


    public void setSelector(String key, ElSelector elBySelector) {
        selectorMap.put(key, elBySelector);
    }

    public ElSelector getSelector(String key) {
        return selectorMap.get(key);
    }

}
